﻿#include "Snake.h"

//首页面
void FirstPage()
{
	printf("\n\n\n\n\n\n\n\n\n");
	printf("\t\t\t\t\t        》》》欢迎进入游戏贪吃蛇《《《\n");
	printf("\t\t\t\t\t    》》》通过按键W A S D控制蛇的运动《《《\n");
	printf("\t\t\t\t\t》》》☆加10分★加20分♂加30分♀加40分▼减25分《《《\n\n");
	printf("\t\t\t\t\t##############################################\n");
	printf("\t\t\t\t\t       温馨提示：请将键盘切换到英文状态       \n");
	printf("\t\t\t\t\t##############################################\n\n");
	printf("\t\t\t\t\t       》》》按空格键进入难度选择《《《\n");
	printf("\t\t\t\t\t    》》》按Enter键开始游戏（默认简单）《《《\n");
	printf("\t\t\t\t\t         》》》按Esc键退出游戏《《《\n");
}

//难度选择页面
void DifficultyPage()
{
	system("cls");//控制台清屏
	printf("\n\n\n\n\n");
	printf("\t\t\t\t\t\t1.简单\n");
	printf("\t\t\t\t\t\t2.入门\n");
	printf("\t\t\t\t\t\t3.困难\n");
	printf("\t\t\t\t\t\t4.魔鬼\n\n");
	printf("\t\t\t\t\t\t请键入相应代号：");
}

//加载页面
void LoadingPage()
{
	system("cls");
	printf("游戏即将开始>>>>>       Loading\n");
	Sleep(1000);
	system("cls");
}

//失败页面
void FailedPage()
{
	system("cls");
	printf("\n\n\n\n\n\n\n");
	printf("\t\t\t\t\t\t***************\n");
	printf("\t\t\t\t\t\t* GameOver!!! *\n");
	printf("\t\t\t\t\t\t***************\n");
	printf("\t\t\t\t\t\t您的最终得分：%d\n", TotaScore);
}

//胜利页面
void WinPage()
{
	system("cls");
	printf("\n\n\n\n\n\n\n");
	printf("\t\t\t\t\t\t***************\n");
	printf("\t\t\t\t\t\t*   Victory   *\n");
	printf("\t\t\t\t\t\t***************\n");
	printf("\t\t\t\t\t\t您的最终得分：%d\n", TotaScore);
}

//检测输入键值
int StartInput()
{
	char GameFlg;

	for (;;)
	{
		GameFlg = getch();
		switch (GameFlg)
		{
		case 32:
			DifficultyPage();
			int DifficultyFlg;

			for (;;)
			{
				int ScanfFlg;
				ScanfFlg = scanf("%i", &DifficultyFlg);
				if (!ScanfFlg)
				{
					printf("难度选择出错！即将退出\n");
					system("pause");//屏幕冻结
					exit(0);
				}
				switch (DifficultyFlg)
				{
				case 1:
					LoadingPage();
					return 1000;//可以不使用break
				case 2:
					LoadingPage();
					return 500;
				case 3:
					LoadingPage();
					return 250;
				case 4:
					LoadingPage();
					return 100;
				default:
					printf("！！！没有该操作代号\n请重新键入：");
				}
			}
		case 13:
			LoadingPage();
			return 1000;
		case 27:
			exit(0);
		default:
			printf("按键错误！没有该操作！请重新键入！\n");
		}
	}
}

//显示游戏背景图案
void GameBackground()
{
	printf("\n\n\n");
	for (int i = 0; i < BG_HEIGHT; i++)
	{
		printf("\t\t\t\t%s",Background[i]);
	}
	printf("\n\t\t\t\t&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n");
	printf("\t\t\t\t总得分：%d\n", TotaScore);
}

//画蛇
void DrawSnake()
{
	strncpy(&Background[Snake_X[0]][Snake_Y[0]], "⊙", 2);//头部
	for (int i = 1; i < SnakeLength; i++)
	{
		strncpy(&Background[Snake_X[i]][Snake_Y[i]], "□", 2);//躯干
	}
}

//产生开始的随机蛇
void RandSnake()
{
	int SnakeHead_X, SnakeHead_Y;

	srand((unsigned)time(NULL));//用当前系统的时间来确定随机种子
	//rand()%(max-min+1)+min;
	SnakeHead_X = rand() % (BG_HEIGHT-8) + 4;//4-15 
	SnakeHead_Y = rand() % (BG_WIDTH / 2 - 7) + 4;//4-18

	SnakeLength = 2;
	//初始蛇的两段身体
	Snake_X[0] = SnakeHead_X;
	Snake_Y[0] = 2 * SnakeHead_Y;
	Snake_X[1] = SnakeHead_X;
	Snake_Y[1] = 2 * (SnakeHead_Y + 1);

	DrawSnake();
}

//产生食物
void FoodProduce()
{
	if (ReProduceFood == FALSE)//当ReProduceFood为FALSE时，提前结束食物产生函数
	{
		return;
	}

	//保证食物不与身体重叠
	BOOL FoodFlg = TRUE;
	while (1)
	{
		srand((unsigned)time(NULL));
		Food_X = rand() % (BG_HEIGHT - 2) + 1;
		Food_Y = rand() % (BG_WIDTH / 2 - 3) + 1;

		for (int i = 0; i < SnakeLength; i++)
		{
			if (Snake_X[i] == Food_X && Snake_Y[i] == Food_Y * 2)
			{
				FoodFlg = FALSE;
				break;
			}
		}

		//真正产生食物
		int FoodTypeFlg;
		srand((unsigned)time(NULL));
		FoodTypeFlg = rand() % 100;
		if (FoodFlg)
		{
			if (FoodTypeFlg < 30)//概率30%
			{
				strncpy(&Background[Food_X][Food_Y * 2], "☆", 2);
				FoodType = HollowPentagon;
			}
			else if (FoodTypeFlg >= 30 && FoodTypeFlg < 55)//概率25%
			{
				strncpy(&Background[Food_X][Food_Y * 2], "★", 2);
				FoodType = SolidPentagon;
			}
			else if (FoodTypeFlg >= 55 && FoodTypeFlg < 75)//概率20%
			{
				strncpy(&Background[Food_X][Food_Y * 2], "♂", 2);
				FoodType = Male;
			}
			else if (FoodTypeFlg >= 75 && FoodTypeFlg < 90)//概率15%
			{
				strncpy(&Background[Food_X][Food_Y * 2], "♀", 2);
				FoodType = Female;
			}
			else if (FoodTypeFlg >= 90 && FoodTypeFlg < 100)//概率10%
			{
				strncpy(&Background[Food_X][Food_Y * 2], "▼", 2);
				FoodType = Triangle;
			}
			ReProduceFood = FALSE;
			break;
		}
	}
}

//检测键盘输入的方向
void GetKeyDirection()
{
	if (GetAsyncKeyState('W'))
	{
		if (SnakeHeadDirection != Down)//错误方向判断
		{
			SnakeHeadDirection = Up;
		}
	}
	else if (GetAsyncKeyState('A'))
	{
		if (SnakeHeadDirection != Right)
		{
			SnakeHeadDirection = Left;
		}
	}
	else if (GetAsyncKeyState('S'))
	{
		if (SnakeHeadDirection != Up)
		{
			SnakeHeadDirection = Down;
		}
	}
	else if (GetAsyncKeyState('D'))
	{
		if (SnakeHeadDirection != Left)
		{
			SnakeHeadDirection = Right;
		}
	}
	else if (GetAsyncKeyState(VK_TAB))//Tab键暂停
	{
		system("pause");
	}
}

//获取蛇尾运动方向
void GetSnakeFootDirection()
{
	if (Snake_X[SnakeLength - 2] < Snake_X[SnakeLength - 1])
	{
		SnakeFootDirection = Up;
	}
	else if (Snake_X[SnakeLength - 2] > Snake_X[SnakeLength - 1])
	{
		SnakeFootDirection = Down;
	}
	else if (Snake_Y[SnakeLength - 2] < Snake_Y[SnakeLength - 1])
	{
		SnakeFootDirection = Left;
	}
	else if (Snake_Y[SnakeLength - 2] > Snake_Y[SnakeLength - 1])
	{
		SnakeFootDirection = Right;
	}
}

void SnakeMove()
{
	GetSnakeFootDirection();

	//清除之前的蛇身
	strncpy(&Background[Snake_X[SnakeLength - 1]][Snake_Y[SnakeLength - 1]], "  ", 2);

	for (int i = SnakeLength - 1; i > 0; i--)
	{
		Snake_X[i] = Snake_X[i-1];
		Snake_Y[i] = Snake_Y[i-1];
	}

	if (SnakeHeadDirection == Up)
	{
		Snake_X[0]--;
	}
	else if (SnakeHeadDirection == Down)
	{
		Snake_X[0]++;
	}
	else if (SnakeHeadDirection == Left)
	{
		Snake_Y[0] = Snake_Y[0] - 2;
	}
	else if (SnakeHeadDirection == Right)
	{
		Snake_Y[0] = Snake_Y[0] + 2;
	}

	DrawSnake();
}

//蛇的死亡判断（两种情况）:撞墙，碰到自身
BOOL SnakeDeath()
{
	//一、撞墙
	if (Snake_X[0] == 0 || Snake_X[0] == BG_HEIGHT - 1)
	{
		return TRUE;
	}
	if (Snake_Y[0] == 0 || Snake_Y[0] == BG_WIDTH - 4)
	{
		return TRUE;
	}

	//二、碰到自身
	for (int i = 1; i < SnakeLength; i++)
	{
		if (Snake_X[0] == Snake_X[i] && Snake_Y[0] == Snake_Y[i])
		{
			return TRUE;
		}
	}

	return FALSE;
}

//游戏胜利判断：蛇的长度达到50或总得分达到1000
BOOL SnakeVictory()
{
	if (SnakeLength == 50 || TotaScore == 1000)
	{
		return TRUE;
	}

	return FALSE;
}

//统计得分
void FinalScoring()
{
	if (FoodType == HollowPentagon)
	{
		TotaScore += 10;
	}
	else if (FoodType == SolidPentagon)
	{
		TotaScore += 20;
	}
	else if (FoodType == Male)
	{
		TotaScore += 30;
	}
	else if (FoodType == Female)
	{
		TotaScore += 40;
	}
	else if (FoodType == Triangle)
	{
		TotaScore -= 25;
	}
}

//蛇吃到食物时的生长逻辑
void SnakeChange()
{
	if (Snake_X[0] == Food_X && Snake_Y[0] == Food_Y * 2 && FoodType == Triangle)
	{
		PlaySound("res/Bad.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);
		ReProduceFood = TRUE;
		FinalScoring();
		return;
	}
	else if (Snake_X[0] == Food_X && Snake_Y[0] == Food_Y * 2)
	{
		if (SnakeFootDirection == Up)
		{
			Snake_X[SnakeLength] = Snake_X[SnakeLength - 1] + 1;
			Snake_Y[SnakeLength] = Snake_Y[SnakeLength - 1];
		}
		else if (SnakeFootDirection == Down)
		{
			Snake_X[SnakeLength] = Snake_X[SnakeLength - 1] - 1;
			Snake_Y[SnakeLength] = Snake_Y[SnakeLength - 1];
		}
		else if (SnakeFootDirection == Left)
		{
			Snake_X[SnakeLength] = Snake_X[SnakeLength - 1];
			Snake_Y[SnakeLength] = Snake_Y[SnakeLength - 1] + 2;
		}
		else if (SnakeFootDirection == Right)
		{
			Snake_X[SnakeLength] = Snake_X[SnakeLength - 1];
			Snake_Y[SnakeLength] = Snake_Y[SnakeLength - 1] - 2;
		}

		PlaySound("res/Add.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);
		ReProduceFood = TRUE;
		FinalScoring();
		SnakeLength++;
		DrawSnake();
	}
}

int main()
{
	//难度传递标志
	int flg;
	
	//cmd窗口设置
	system("title Gluttonous Snake");
	system("color 8B");
	/*0 = 黑色    8 = 灰色
	  1 = 蓝色    9 = 淡蓝色
	  2 = 绿色    A = 淡绿色
	  3 = 浅绿色  B = 淡浅绿色
	  4 = 红色    C = 淡红色
	  5 = 紫色    D = 淡紫色
	  6 = 黄色    E = 淡黄色
	  7 = 白色    F = 亮白色*/
	system("mode con cols=130 lines=30");//控制窗口高度及宽度
	system("ver");

	FirstPage();
	PlaySound("res/Start.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);//游戏开始时背景音乐调用
	flg = StartInput();
	RandSnake();
	system("cls");
	GameBackground();
	PlaySound(NULL, NULL, NULL);//清除音乐播放

	while (1)
	{
		PlaySound("res/Background.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP | SND_NOSTOP | SND_NODEFAULT);
		FoodProduce();
		GetKeyDirection();
		SnakeMove();
		SnakeChange();
		system("cls");
		GameBackground();
		if (SnakeDeath())
		{
			PlaySound("res/Death.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);
			FailedPage();
			system("pause");
			return 0;
		}
		if (SnakeVictory())
		{
			PlaySound("res/Victory.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);
			WinPage();
			system("pause");
			return 0;
		}
		Sleep(flg);
	}
}